package com.yang.sms.mq;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.rabbitmq.client.Channel;
import com.yang.common.amqp.rabbit.ConsumerUtil;
import com.yang.common.core.util.Utils;
import com.yang.sms.core.SendResponse;
import com.yang.sms.core.SmsSender;
import com.yang.sms.entity.SmsTask;
import com.yang.sms.entity.SmsTaskDetail;
import com.yang.sms.entity.SmsTemplate;
import com.yang.sms.entity.SmsTypeTemplateConfig;
import com.yang.sms.enums.Constants;
import com.yang.sms.enums.SmsTaskDetailEnum;
import com.yang.sms.service.SmsTaskDetailService;
import com.yang.sms.service.SmsTaskService;
import com.yang.sms.service.SmsTemplateService;
import com.yang.sms.service.SmsTypeTemplateConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * 短信发送处理器（消费者逻辑）
 * @author Billyang
 * @date 2024/9/27 17:28
 */
@Slf4j
@Component
public class SmsSenderConsumer {
    @Autowired
    private SmsTaskService smsTaskService;
    @Autowired
    private SmsTaskDetailService smsTaskDetailService;
    @Autowired
    private SmsTypeTemplateConfigService smsTypeTemplateConfigService;
    @Autowired
    private SmsTemplateService smsTemplateService;
    @Autowired
    private SmsSender smsSender;

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = Constants.QUEUE.SEND_SMS.NAME),
            exchange = @Exchange(value = Constants.EXCHANGE.DIRECT),
            key = Constants.QUEUE.SEND_SMS.ROUTING_KEY))
    public void handle(String jsonStrMsg, Channel channel, Message message) {
        ConsumerUtil.handleByConsumer(jsonStrMsg, channel, message,this::consumer);
    }

    public void consumer(Integer smsTaskDetailId){
        SmsTaskDetail smsTaskDetail = smsTaskDetailService.selectById(smsTaskDetailId);
        SmsTask smsTask = smsTaskService.selectById(smsTaskDetail.getTaskId());
        String remark = smsTaskDetail.getRemark();

        Integer status = smsTaskDetail.getStatus();
        SmsTaskDetailEnum.Status statusEnum = SmsTaskDetailEnum.Status.of(status);

        if (statusEnum == SmsTaskDetailEnum.Status.REQUEST_SUCCESS || statusEnum == SmsTaskDetailEnum.Status.REQUEST_FAIL
                || statusEnum == SmsTaskDetailEnum.Status.CANCEL_SEND) {
            log.info("状态不匹配 {}:{}", smsTaskDetailId, status);
            remark = Utils.rightRemark(remark, "状态不匹配:" + statusEnum.getDesc());
            smsTaskDetailService.updateRemark(remark, smsTaskDetailId);
            return;
        }

        remark = Utils.rightRemark(remark, SmsTaskDetailEnum.Status.MQ_CONSUME_SUCCESS.getDesc());
        smsTaskDetailService.updateStatusRemark(SmsTaskDetailEnum.Status.MQ_CONSUME_SUCCESS, remark, smsTaskDetailId);

        LocalDateTime overTime = smsTask.getOverTime();
        LocalDateTime now = LocalDateTime.now();
        if (overTime.compareTo(now) < 0) {
            log.info("超时取消发送 {}:{} {}/{}", smsTaskDetailId, smsTaskDetail.getMobile(),
                    DateUtil.formatLocalDateTime(overTime), DateUtil.formatLocalDateTime(now));
            remark = Utils.rightRemark(remark, "超时取消发送");
            smsTaskDetailService.updateStatusRemark(SmsTaskDetailEnum.Status.CANCEL_SEND, remark, smsTaskDetailId);
            return;
        }

        LinkedHashMap<String, String> templateParamMap = JSON.parseObject(smsTaskDetail.getTemplateParamJson(), LinkedHashMap.class);
        String type = smsTask.getType();
        String channel = smsSender.channel();
        SmsTypeTemplateConfig smsTypeTemplateConfig = smsTypeTemplateConfigService.selectByTypeChannel(type, channel);
        if (smsTypeTemplateConfig == null) {
            log.info("业务-模板未配置:{}-{}", type, channel);
            remark = Utils.rightRemark(remark, "业务-模板未配置:" + type + "-" + channel);
            smsTaskDetailService.updateStatusRemark(SmsTaskDetailEnum.Status.CANCEL_SEND, remark, smsTaskDetailId);
            return;
        }

        String templateCode = smsTypeTemplateConfig.getTemplateCode();
        String content = null;
        SmsTemplate smsTemplate = smsTemplateService.selectByChannelTemplateCode(channel, templateCode);
        if (smsTemplate != null) {
            String templateContent = smsTemplate.getTemplateContent();
            content = fillTemplateContent(templateContent, templateParamMap);
        } else {
            if (StringUtils.isBlank(content)) {
                content = String.format("模板sms_template未配置,channel:%s,templateCode:%s", channel, templateCode);
            }
        }
        smsTaskDetailService.updateContentById(content, smsTaskDetailId);

        // 调用短信发送API
        SendResponse response = smsSender.send(smsTaskDetail.getMobile(), templateCode, templateParamMap, content);
        if (response.isSuccess()) {
            remark = Utils.rightRemark(remark, SmsTaskDetailEnum.Status.REQUEST_SUCCESS.getDesc());
            smsTaskDetailService.updateSendSuccessStatus(SmsTaskDetailEnum.Status.REQUEST_SUCCESS, remark, smsTaskDetailId);
        } else {
            remark = Utils.rightRemark(remark, response.getMessage());
            smsTaskDetailService.updateStatusRemark(SmsTaskDetailEnum.Status.REQUEST_FAIL, remark, smsTaskDetailId);
        }
    }

    /**
     * 填充模板内容
     *
     * @param templateContent
     * @return
     */
    private String fillTemplateContent(String templateContent, LinkedHashMap<String, String> templateParamMap) {
        if (templateContent == null) {
            return null;
        }

        String content = templateContent;

        Set<Map.Entry<String, String>> entrySet = templateParamMap.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            String key = entry.getKey();
            String value = entry.getValue();
            content = content.replace(String.format("${%s}", key), value);
        }

        return content;
    }
}
